package com.bsoft.gol.hbs.service.impl;

import com.bsoft.gol.hbs.bean.qo.HealthActivitiesListQo;
import com.bsoft.gol.hbs.dao.HealthActivitiesDAO;
import com.bsoft.gol.hbs.dao.PcnTagsDAO;
import com.bsoft.gol.hbs.utils.CommonUtils;
import com.google.gson.Gson;
import com.security.cipher.sm.SM4Utils;
import ctd.account.UserRoleToken;
import ctd.dictionary.Dictionary;
import ctd.dictionary.DictionaryItem;
import ctd.dictionary.controller.DictionaryController;
import ctd.net.rpc.Client;
import ctd.persistence.annotation.DAOTransaction;
import ctd.spring.boot.annotation.RpcAccess;
import ctd.spring.boot.annotation.SsdevService;
import ctd.util.context.ContextUtils;
import hcn.base.BaseActionRecord;
import hcn.base.Device;
import hcn.base.healthact.HealthActivities;
import hcn.base.healthact.HealthActivitiesService;
import hcn.base.healthact.qo.HealthActivitiesListRequest;
import hcn.base.healthact.qo.HealthActivitiesQo;
import hcn.base.healthact.qo.HealthNewsActionQo;
import hcn.base.healthact.qo.SavePcnHealthActivitiesQo;
import hcn.base.healthact.vo.CmsActionVo;
import hcn.base.healthact.vo.HealthActivitiesAppVO;
import hcn.base.healthact.vo.HealthActivitiesDetailVO;
import hcn.base.healthact.vo.HealthActivitiesVO;
import hcn.base.notification.event.NotificationEvent;
import hcn.bean.PushMessageBean;
import hcn.enums.MsgTemplateCode;
import hcn.util.RpcUserToken;
import org.apache.commons.collections.map.HashedMap;
import org.atag.dao.model.SimplePageInfo;
import org.atag.util.common.RpcUtil;
import org.atag.util.common.SpringPropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import pcn.enums.CmsActionEnum;
import pcn.enums.RoleIdEnum;
import pcn.enums.TagsTypeEnum;
import pcn.sign.MpiIdentity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author linyi
 * @date 2021/11/15 17:18
 */
@SsdevService("healthActivities")
public class HealthActivitiesServiceImpl implements HealthActivitiesService {
    private static final Logger LOGGER = LoggerFactory.getLogger(HealthActivitiesServiceImpl.class);
    @Autowired
    private HealthActivitiesDAO healthActivitiesDAO;

    @Autowired
    private BaseActionRecordService baseActionRecordService;
    @Autowired
    private PcnTagsDAO pcnTagsDAO;
//    private PcnTagsIndexService pcnTagsIndexService;

    public interface Constant {

        String BUSINESS_TYPE = "activity";
        String MARK = "mark";
        String LIKES = "likes";
    }

    /**
     * 保存/修改
     */
    @Override
    @DAOTransaction
    public void savePcnHealthActivities(SavePcnHealthActivitiesQo healthActivities) throws Exception {

        UserRoleToken current = UserRoleToken.getCurrent();

        if (CommonUtils.isNotEmpty(healthActivities.getDiseaseGroup())) {
            List<SavePcnHealthActivitiesQo.Item> diseaseGroup = healthActivities.getDiseaseGroup();
            List<String> idCollect = diseaseGroup.stream().map(SavePcnHealthActivitiesQo.Item::getId).collect(Collectors.toList());
            List<String> nameCollect = diseaseGroup.stream().map(SavePcnHealthActivitiesQo.Item::getName).collect(Collectors.toList());
            healthActivities.setDiseaseGroupList(String.join(",", idCollect));
            healthActivities.setDiseaseGroupName(String.join(",", nameCollect));
        }
        if (CommonUtils.isNotEmpty(healthActivities.getPersonGroup())) {
            List<SavePcnHealthActivitiesQo.Item> personGroup = healthActivities.getPersonGroup();
            List<String> idCollect = personGroup.stream().map(SavePcnHealthActivitiesQo.Item::getId).collect(Collectors.toList());
            List<String> nameCollect = personGroup.stream().map(SavePcnHealthActivitiesQo.Item::getName).collect(Collectors.toList());
            healthActivities.setPersonGroupList(String.join(",", idCollect));
            healthActivities.setPersonGroupName(String.join(",", nameCollect));
        }
        if (CommonUtils.isNull(healthActivities.getId())) {
            if (current != null) {
                healthActivities.setCreateUser(current.getUserName());
            }
            healthActivities.setReadCount(0);
            healthActivities.setCollectCount(0);
            healthActivities.setShareCount(0);
            healthActivities.setPraiseCount(0);
            healthActivities.setStatus((byte) 0);
            healthActivities.setCreateDt(new Date());
            healthActivitiesDAO.save(healthActivities);
            HealthActivities tpha = healthActivities;
            String flag = "0";
            String tenantId = RpcUserToken.getTenantId();
            try {
                dealInfoForSend(tpha, flag, tenantId);
            } catch (Exception e) {
                LOGGER.error("保存时！发送消息失败！");
                e.printStackTrace();

            }
        } else {
            healthActivities.setLastModifyDt(new Date());
            healthActivities.setLastModifyUser(current.getUserName());
            healthActivitiesDAO.updateById(healthActivities);
        }

//        pcnTagsIndexService.saveIndex(TagsTypeEnum.healthActivitType.name(), String.valueOf(pcnHealthActivities.getId()), pcnHealthActivities.getAtype());

    }

    /**
     * 处理发送的消息内容
     *
     * @param healthActivities
     * @param flag                0新增的时候推送 1删除的时候推送
     */
    public void dealInfoForSend(HealthActivities healthActivities, String flag, String tenantId) throws Exception {
        //发送消息
        String context;
        String peopleGroup = healthActivities.getPersonGroupList();
        Map<String, String> parameMap = new HashedMap();
        parameMap.put("id", healthActivities.getId() + "");
        parameMap.put("img", healthActivities.getImg());
        String title;
        //消息内容
        context = megDetail(healthActivities, flag, parameMap);
        //判断是活动还是讲座  1活动 2讲座
        title = "1".equals(healthActivities.getAtype()) ? ("0".equals(flag) ? "健康活动通知" : "取消活动通知") : ("0".equals(flag) ? "健康讲座通知" : "取消讲座通知");
        //发送消息
        LOGGER.info("title:" + title);
        if (CommonUtils.isNotEmpty(peopleGroup)){
            notify(peopleGroup, context, title, parameMap, tenantId, healthActivities, flag);
        }

    }

    /**
     * 处理消息内容
     */
    private String megDetail(HealthActivities healthActivities, String flag, Map<String, String> map) {
        String meg;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String startTime = format.format(healthActivities.getStartTime());
        String endTime = format.format(healthActivities.getEndTime());
        //1删除 0新增
        if ("0".equals(flag)) {
            meg = healthActivities.getTitle() + "，" + "将于"
                    + startTime + "至" + endTime + "在" + healthActivities.getAddress() + "举办，欢迎参加!";
            map.put("flag", "0");
        } else {
            meg = "很抱歉通知您，原定于" + startTime + "至" + endTime + "在" + healthActivities.getAddress() + "举办的" + healthActivities.getContact() + "，已经取消";
            //1删除
            map.put("flag", "1");
        }

        return meg;
    }

    /**
     * 维护阅读量
     */
    @Override
    public void updateReadCountEdit(Integer id, Integer num) {
        healthActivitiesDAO.updateReadCountEdit(id, num);
    }

    /**
     * 删除
     *
     * @param id
     * @throws Exception
     */
    @Override
    public void deletePcnHealthActivities(Integer id) throws Exception {
        //查询出删除的活动
        HealthActivities healthActivities = healthActivitiesDAO.get(id);
        healthActivitiesDAO.updateStatus((byte) 1, id);
//        pcnTagsIndexService.removeIndex(TagsTypeEnum.healthActivitType.name(), String.valueOf(id));
        HealthActivities tpha = healthActivities;
        String flag = "1";
        String tenantId = RpcUserToken.getTenantId();
        try {
            dealInfoForSend(tpha, flag, tenantId);
        } catch (Exception e) {
            LOGGER.error("删除时！发送消息失败！" + e.getCause().getMessage());
        }
    }

    /**
     * 查看、记录阅读量
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public HealthActivities detailInfo(Integer id) throws Exception {
        return healthActivitiesDAO.get(id);
    }

    /**
     * 查看、记录阅读量
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @RpcAccess(auth = true)
    public HealthActivitiesDetailVO detailInfoForH5(Integer id) throws Exception {
        HealthActivitiesDetailVO vo = new HealthActivitiesDetailVO();
        HealthActivities pha = healthActivitiesDAO.get(id);
        //每次打开详情页面增加一次阅读量
        if (CommonUtils.isNotEmpty(pha.getJobTitle())) {
            Dictionary gender = DictionaryController.instance().get("pcn.base.dictionary.doctorTitle");
            if(null != gender) {
                DictionaryItem item = gender.getItem(pha.getJobTitle());
                if (item != null) {
                    String spearkerType = item.getText();
                    pha.setJobTitle(spearkerType);
                } else {
                    pha.setJobTitle("无");
                }
            }
        } else {
            pha.setJobTitle("无");
        }
        BeanUtils.copyProperties(pha, vo);
        healthActivitiesDAO.updateReadCount(id);

        UserRoleToken current = UserRoleToken.getCurrent();
        if(null != current && CommonUtils.isNotEmpty(current.getUserId())){
            String userId = current.getUserId();
            //获取当前用户是否对当前活动或者收藏
            BaseActionRecord likesAction = baseActionRecordService.getByBizKey(id.toString(), Constant.BUSINESS_TYPE, Constant.LIKES, userId);
            BaseActionRecord markAction = baseActionRecordService.getByBizKey(id.toString(), Constant.BUSINESS_TYPE, Constant.MARK, userId);

            vo.setLikes(CommonUtils.isNotEmpty(likesAction));
            vo.setCollection(CommonUtils.isNotEmpty(markAction));
        }

        return vo;
    }


    @Override
    public void updateReadCount(Integer id) throws Exception {
        healthActivitiesDAO.updateReadCount(id);
    }

    /**
     * 添加到动作表
     */
    @Override
    public CmsActionVo updateNewsAction(HealthNewsActionQo qo) throws Exception {

        CmsActionVo resultVo = new CmsActionVo();
        Integer id = qo.getId();
        String action = qo.getAction();
        String userId = UserRoleToken.getCurrent().getUserId();

        //只有收藏和点赞是唯一次的 分享是可以多次的
        BaseActionRecord dbRecord = null;
        if ("likes".equals(action) || "mark".equals(action)) {
            dbRecord = baseActionRecordService.getByBizKey(id.toString(), Constant.BUSINESS_TYPE, action, userId);
        }
        if (CommonUtils.isEmpty(dbRecord)) {
            BaseActionRecord insert = new BaseActionRecord();
            insert.setAction(action);
            insert.setBusinessType(Constant.BUSINESS_TYPE);
            insert.setBusinessId(id.toString());
            insert.setUserId(userId);
            insert.setGmtCreate(new Date());

            baseActionRecordService.saveAction(insert);

            if (CmsActionEnum.likes.name().equals(action)) {
                healthActivitiesDAO.updatePraiseCount(id);
            } else if (CmsActionEnum.mark.name().equals(action)) {
                healthActivitiesDAO.updateCollectCount(id);
            } else if (CmsActionEnum.share.name().equals(action)) {
                healthActivitiesDAO.updateShareCount(id);
            }
            resultVo.setRemark("0");
        } else {
            baseActionRecordService.removeAction(id.toString(), Constant.BUSINESS_TYPE, action, userId);
            //点赞减一 收藏不减
            if (CmsActionEnum.likes.name().equals(action)) {
                healthActivitiesDAO.updatePraiseCountRedice(id);
            } else if (CmsActionEnum.mark.name().equals(action)) {
                //收藏减一 点赞不减
                healthActivitiesDAO.updateCollectCountRedice(id);
            }
            resultVo.setRemark("1");
        }
        return resultVo;

    }

    /**
     * 查询列表
     *
     * @param phqo
     * @return
     * @throws Exception
     */
    @Override
    @RpcAccess(auth = false)
    public HealthActivitiesAppVO getPcnHealthActivitiesList(HealthActivitiesQo phqo) throws Exception {
        //接口无需token，默认取环境变量配置的租户id
        String tenantId = (String)ContextUtils.get("$tenantId");
        if(null == tenantId){
            tenantId = SpringPropertiesUtil.get("tenantId");
            LOGGER.info("tenantId="+tenantId);
            ContextUtils.put("$tenantId",tenantId);
        }

        try {
            HealthActivitiesAppVO vo = healthActivitiesDAO.getPcnHealthActivities(phqo);

            if (CommonUtils.isNotEmpty(vo)){
                List<HealthActivitiesVO> healthActivitiesVOs=vo.getList();
                if (CommonUtils.isNotEmpty(healthActivitiesVOs)){
                    for (HealthActivitiesVO healtha : healthActivitiesVOs) {
                        //人群分类列表
                        List<SavePcnHealthActivitiesQo.Item> pList = contactGroupList(healtha.getPersonGroupList(), healtha.getPersonGroupName());
                        healtha.setPersonGroup(pList);
                        List<SavePcnHealthActivitiesQo.Item> dList = contactGroupList(healtha.getDiseaseGroupList(), healtha.getDiseaseGroupName());
                        healtha.setDiseaseGroup(dList);
                    }
                }

            }
            // 从标签获得栏目列表
            List<Map<String, String>> tagsList = pcnTagsDAO.findCodeAndNameByTypeCode(tenantId, TagsTypeEnum.healthActivitType.name());

            Map tags = new HashedMap();
            tags.put("tagCode", "0");
            tags.put("tagName", "全部");
            tagsList.add(0, tags);
            vo.setTaglist(tagsList);
            return vo;

        } catch (Exception e) {
            LOGGER.error("查询列表失败" + e.getCause().getMessage());
        }
        return null;

    }

    private List<SavePcnHealthActivitiesQo.Item> contactGroupList(String idList, String nameList) {
        List<SavePcnHealthActivitiesQo.Item> tempList = new ArrayList<>();
        if (CommonUtils.isNotEmpty(idList)) {
            String[] idArray = idList.split(",");
            String[] nameArray = new String[0];
            if (CommonUtils.isNotEmpty(nameList)) {
                nameArray = nameList.split(",");
            }
            for (int i = 0; i < idArray.length; i++) {
                SavePcnHealthActivitiesQo.Item item = new SavePcnHealthActivitiesQo.Item();
                item.setId(idArray[i]);
                item.setName(i > nameArray.length - 1 ? "" : nameArray[i]);
                tempList.add(item);
            }
        }
        return tempList;
    }

    /**
     * 获取用户的收藏信息
     *
     * @param qo
     * @return
     * @throws Exception
     */
    @Override
    public SimplePageInfo<HealthActivities> getUserMarkInfo(HealthActivitiesListRequest qo) throws Exception {
        String userId = UserRoleToken.getCurrent().getUserId();
        List<String> ids = baseActionRecordService.getBusinessIdList(Constant.BUSINESS_TYPE, Constant.MARK, userId);

        if(CommonUtils.isEmpty(ids)){
            return new SimplePageInfo<>();
        }
        List<Integer> collect = ids.stream().map(Integer::valueOf).collect(Collectors.toList());
        HealthActivitiesListQo qo1 = new HealthActivitiesListQo();
        qo1.setIds(collect);
        qo1.setPageNo(qo.getPageNo());
        qo1.setPageSize(qo.getPageSize());
        qo1.setAtype(qo.getAtype());

        return healthActivitiesDAO.getActivitiesPage(qo1);

    }

    @Override
    public void updatePcnHealthActivities(HealthActivities healthActivities) throws Exception {
        healthActivitiesDAO.update(healthActivities);
//        pcnTagsIndexService.saveIndex(TagsTypeEnum.healthActivitType.name(), String.valueOf(pcnHealthActivities.getId()), pcnHealthActivities.getAtype());
    }

    /**
     * 发送消息
     *
     * @param peopleGroup
     * @param content
     * @param map
     * @param title
     * @throws Exception
     */

    public void notify(String peopleGroup, String content, String title, Map<String, String> map, String tenantId, HealthActivities healthActivities, String flag) throws Exception {
        String[] group = peopleGroup.split(",");
        List<String> groupList = Arrays.asList(group);

        //获取到mpiId 的列表
        List<String> mpiIds = RpcUtil.invoke("pcn.pcnSignPersonGroupService", "findMpiIdListByPersonGroup", groupList);
        //根据mpiId 查询 实际的 userID
        if (CommonUtils.isEmpty(mpiIds)) {
            return;
        }
        List<MpiIdentity> mpiList = RpcUtil.invoke("pcn.mpiIdentityService", "queryIdOrNolistByMpiIdList", mpiIds);
        if (CommonUtils.isEmpty(mpiList)) {
            return;
        }
        //解密出实际的userId
        List<String> userIds = mpiList.stream().map(MpiIdentity::getIdOrNo).map(SM4Utils::decryptData_ECB).collect(Collectors.toList());
        LOGGER.info("查询到：{} 个人,idList: {}", userIds.size(), new Gson().toJson(userIds));
        try {
            //rpc 调用 获取设备
            List<Device> deviceList = RpcUtil.invoke("pcn.baseDeviceDAOService", "findOnLineDevicesByUserIds", userIds, "patient", tenantId);
            LOGGER.info("查询到：{}个设备，deviceList:{}", deviceList.size(), new Gson().toJson(deviceList));
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String startTime = format.format(healthActivities.getStartTime());
            String endTime = format.format(healthActivities.getEndTime());
            for (Device device : deviceList) {
                //发送极光消息
                PushMessageBean pushMessageBean = new PushMessageBean();
                pushMessageBean.setRoleId(RoleIdEnum.PATIENT.title());
                pushMessageBean.setNotificateType(String.valueOf(NotificationEvent.NotificateType.health_activities_patient));
                pushMessageBean.setUserId(device.getUserId());
                pushMessageBean.setMsgTitle(title);
                Map<String, String> variableMap = new HashMap<String, String>();
                if ("0".equals(flag)) {//健康宣教参会通知
                    pushMessageBean.setTemplateCode(MsgTemplateCode.HEALTH_ACTIVITIES_PATIENT.getCode());
                    variableMap.put("#会议标题#", healthActivities.getTitle());
                    variableMap.put("#开始时间#", startTime);
                    variableMap.put("#结束时间#", endTime);
                    variableMap.put("#会议地址#", healthActivities.getAddress());
                } else {//健康宣教取消通知
                    pushMessageBean.setTemplateCode(MsgTemplateCode.HEALTH_ACTIVITIESCANCELED_PATIENT.getCode());
                    variableMap.put("#开始时间#", startTime);
                    variableMap.put("#结束时间#", endTime);
                    variableMap.put("#会议地址#", healthActivities.getAddress());
                    variableMap.put("#会议标题#", healthActivities.getContact());
                }
                pushMessageBean.setMsgVariableMap(variableMap);
                if (map != null) {
                    LOGGER.info("map:" + map.toString());
                    pushMessageBean.setExtras(map);
                }
                List<Device> docDeviceList = new ArrayList<Device>();
                docDeviceList.add(device);
                pushMessageBean.setDeviceList(docDeviceList);
                try {
                    Client.rpcInvoke("hcn.sendAllKindsMsgService", "productionMessage", pushMessageBean);
                } catch (Throwable e) {
                    LOGGER.error("MedDrugAppServiceImpl里hcn.messageSyncService执行失败，原因:" + e.getMessage());
                }
            }

            LOGGER.info("健康消息发送成功！");
        } catch (Exception e) {
            LOGGER.error("发送健康宣教消息失败" + e.getCause().getMessage());
        }
    }


}